package com.ccp.dev.form.controller;

import com.ccp.dev.core.basic.annotion.Action;
import com.ccp.dev.core.basic.consts.UrlConstants;
import com.ccp.dev.core.basic.db.datasource.DbContextHolder;
import com.ccp.dev.core.basic.internationalization.SysBaseController;
import com.ccp.dev.core.basic.model.SysAuditModelType;
import com.ccp.dev.core.basic.response.ResultData;
import com.ccp.dev.core.basic.table.BaseTableMeta;
import com.ccp.dev.core.basic.table.TableModel;
import com.ccp.dev.core.basic.util.ContextUtil;
import com.ccp.dev.core.basic.util.PinyinUtil;
import com.ccp.dev.core.basic.util.UUIDUtils;
import com.ccp.dev.core.basic.web.query.QueryFilter;
import com.ccp.dev.core.util.*;
import com.ccp.dev.core.util.log.SysAuditThreadLocalHolder;
import com.ccp.dev.form.consts.FormConstants;
import com.ccp.dev.form.model.*;
import com.ccp.dev.form.service.*;
import com.ccp.dev.form.table.TableMetaFactory;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.text.StringEscapeUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

/**
 * BPM_FORM_TABLE 控制器类
 *
 * @author zhaowj
 */
@Controller
@RequestMapping(UrlConstants.PROJECT_ROOT + UrlConstants.PROJECT_MODULE_FORM + "/table")
@Action(ownermodel = SysAuditModelType.FORM_MANAGEMENT)
public class FormTableController extends SysBaseController {

    @Resource
    private FormTableService formTableService;

    @Resource
    private FormDefService formDefService;

    @Resource
    private FormFieldService formFieldService;

    @Resource
    private FormDialogService formDialogService;

    @Resource
    private SubTableRightsService subTableRightsService;

    @Resource
    private FormCombinationDialogService formCombinationDialogService;

    @Value("${mybatis.configuration.database-id}")
    private String dataSourceType;

    /**
     * 自定义表列表页面跳转
     *
     * @return 页面路径
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX + "/list")
    @Action(description = "自定义表列表页面跳转",exectype = "页面跳转日志")
    public String tableList() {
        return getAutoView();
    }

    /**
     * 页面跳转添加页面
     *
     * @return 页面路径
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX + "/add")
    @Action(description = "自定义表添加页面跳转",exectype = "页面跳转日志")
    public String addTable(HttpServletRequest request, Model model) {
        String categoryId = RequestUtil.getString(request, "categoryId");
        String tableId = RequestUtil.getString(request, "tableId");
        int isExternal = RequestUtil.getInt(request, "isExternal");
        model.addAttribute("tableId", tableId);
        model.addAttribute("categoryId", categoryId);
        model.addAttribute("isExternal", isExternal);
        return getAutoView();
    }

    /**
     * 页面跳转添加列页面
     *
     * @return 页面路径
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX + "/addCol")
    @Action(description = "自定义表添加列页面跳转",exectype = "页面跳转日志")
    public String addCol(HttpServletRequest request, Model model) {
        String isAdd = RequestUtil.getString(request, "isAdd");
        String editIndex = RequestUtil.getString(request, "editIndex");
        String tableId = RequestUtil.getString(request, "tableId");
        String editFieldName = RequestUtil.getString(request, "editFieldName");
        int isExternal = RequestUtil.getInt(request, "isExternal");
        model.addAttribute("tableId", tableId);
        model.addAttribute("isAdd", isAdd);
        model.addAttribute("editIndex", editIndex);
        model.addAttribute("editFieldName", editFieldName);
        model.addAttribute("isExternal", isExternal);
        return getAutoView();
    }


    /**
     * 页面跳转复制页面
     *
     * @return 页面路径
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX + "/copy")
    @Action(description = "自定义表复制页面跳转",exectype = "页面跳转日志")
    public String copy(HttpServletRequest request, ModelMap modelMap) {
        String tableId = RequestUtil.getString(request, "tableId");
        FormTable bpmFormTable = formTableService.getByTableId(tableId, FormField.FIELD_NORMAL);
        String isSubTable = FormConstants.STR_FALSE;
        if (BeanUtils.isNotEmpty(bpmFormTable) && BeanUtils.isNotEmpty(bpmFormTable.getSubTableList())) {
            isSubTable = FormConstants.STR_TRUE;
        }
        if (FormConstants.STR_FALSE.equals(isSubTable)) {
            FormTable table = new FormTable();
            table.setTableId("");
            table.setTableDesc("");
            table.setTableName("");
            List<FormTable> subTList = new ArrayList<>();
            subTList.add(table);
            bpmFormTable.setSubTableList(subTList);
        }
        modelMap.put("isSubTable", isSubTable);
        modelMap.put("bpmFormTable", bpmFormTable);
        return getAutoView();
    }

    /**
     * 页面跳转外部表编辑页面
     *
     * @return 页面路径
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX + "/editExternalTable")
    @Action(description = "自定义表外部表编辑页面跳转",exectype = "页面跳转日志")
    public String extTabEdit(HttpServletRequest request) {
        String tableName = RequestUtil.getString(request, "tableName");
        String dataSource = RequestUtil.getString(request, "dataSource");
        String closeIndex = RequestUtil.getString(request, "closeIndex");
        request.setAttribute("tableName", tableName);
        request.setAttribute("dataSource", dataSource);
        request.setAttribute("closeIndex", closeIndex);
        return getAutoView();
    }


    /**
     * 跳转明细页面
     *
     * @return 页面路径
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX + "/detailed")
    @Action(description = "自定义表明细页面跳转",exectype = "页面跳转日志")
    public String detailed(HttpServletRequest request, Model model) {
        String tableId = RequestUtil.getString(request, "tableId");
        model.addAttribute("tableId", tableId);
        return getAutoView();
    }

    /**
     * 导出页面
     *
     * @return 页面路径
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX + "/export")
    @Action(description = "自定义表导出页面跳转",exectype = "页面跳转日志")
    public String export(HttpServletRequest request) {
        String tableIds = RequestUtil.getString(request, "tableIds");
        request.setAttribute("tableIds", tableIds);
        return getAutoView();
    }

    /**
     * 导入页面
     *
     * @return 页面路径
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX + "/import")
    @Action(description = "自定义表导入页面跳转",exectype = "页面跳转日志")
    public String importView() {
        return getAutoView();
    }

    /**
     * 页面跳转分组页面
     *
     * @return 页面路径
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX + "/grouping")
    @Action(description = "自定义表分组页面跳转",exectype = "页面跳转日志")
    public String grouping(HttpServletRequest request) {
        String tableId = RequestUtil.getString(request, "tableId");
        FormTable bpmFormTable = formTableService.getOneById(tableId);
        request.setAttribute("formTable", bpmFormTable);
        return getAutoView();
    }

    /**
     * 页面跳转选择表页面
     *
     * @return 页面路径
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX + "/generTable")
    @Action(description = "自定义表选择表页面跳转",exectype = "页面跳转日志")
    public String generTable(HttpServletRequest request, Model model) {
        String param = RequestUtil.getString(request, "parentName");
        model.addAttribute("parentName", param);
        return getAutoView();
    }

    /**
     * 页面跳转添加外部表
     *
     * @return 页面路径
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX + "/addExternalTable")
    @Action(description = "自定义表跳转添加外部表页面",exectype = "页面跳转日志")
    public String addExternalTable() {
        return getAutoView();
    }

    /**
     * 添加外部表页面跳转
     *
     * @return 页面路径
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX + "/outTable")
    @Action(description = "添加外部表页面跳转",exectype = "页面跳转日志")
    public String outTable() {
        return getAutoView();
    }

    /**
     * 页面跳转脚本页面
     *
     * @return 页面路径
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX + "/script")
    @Action(description = "脚本页面跳转",exectype = "页面跳转日志")
    public String script(HttpServletRequest request, Model model) {
        String param = RequestUtil.getString(request, "param");
        model.addAttribute("param", param);
        String parentName = RequestUtil.getString(request, "parentName");
        model.addAttribute("parentName", parentName);
        String scriptObj = RequestUtil.getString(request, "scriptObj");
        model.addAttribute("scriptObj", scriptObj);
        return getAutoView();
    }

    /**
     * 页面跳转脚本页面
     *
     * @return 页面路径
     */
    @RequestMapping(UrlConstants.VIEW_DISPATCH_PREFIX + "/templateScript")
    @Action(description = "脚本页面跳转",exectype = "页面跳转日志")
    public String templateScript(HttpServletRequest request, Model model) {
        String ids = RequestUtil.getString(request, "ids");
        String names = RequestUtil.getString(request, "names");
        model.addAttribute("ids", ids);
        model.addAttribute("names", names);
        return getAutoView();
    }

    /**
     * 生成表
     *
     * @param tableId 表ID
     * @return 返回结果JSON数据
     */
    @RequestMapping("/generateTable")
    @ResponseBody
    @Action(description = "生成表", exectype = "操作日志",
            detail = "生成表<#if success>成功<#else>失败</#if>")
    public ResultData publish(@RequestParam("tableId") String tableId) {
        try {
            String operator = ContextUtil.getCurrentUser().getFullName();
            formTableService.generateTable(tableId, operator);
            SysAuditThreadLocalHolder.putParamerter("success", true);
        } catch (Exception e) {
            e.printStackTrace();
            SysAuditThreadLocalHolder.putParamerter("success", false);
            return getResultDataError("formTable.publish.failure");
        }
        return getResultDataSuccess("formTable.publish.success");
    }

    /**
     * 根据表单定义key查询对应表属性字段
     *
     * @param formKey 表单定义key
     * @return 封装对象
     */
    @RequestMapping("/fieldList")
    @ResponseBody
    @Action(description = "根据表单定义key查询对应表属性字段", exectype = "操作日志",
            detail = "根据表单定义key查询对应表属性字段<#if success>成功<#else>失败</#if>")
    public ResultData queryFieldList(@RequestParam String formKey) {
        List<FormField> fieldList;
        try {
            FormDef formDef = formDefService.getDefaultPublishedByFormKey(formKey);
            fieldList = formFieldService.getByTableIdContainHidden(formDef.getTableId());
            SysAuditThreadLocalHolder.putParamerter("success", true);
        } catch (Exception e) {
            e.printStackTrace();
            SysAuditThreadLocalHolder.putParamerter("success", false);
            return getResultDataError("operate.failure");
        }
        return getResultDataSuccess("operate.success", fieldList);
    }

    /**
     * 取得自定义表的分页列表
     *
     * @param request 请求
     * @return 表集合
     */
    @ResponseBody
    @RequestMapping(UrlConstants.MODULE_FUNCTION_LIST)
    @Action(description = "取得自定义表的分页列表", exectype = "查询日志",
            detail = "取得自定义表的分页列表<#if success>成功<#else>失败</#if>")
    public ResultData list(HttpServletRequest request) {
        QueryFilter queryFilter;
        List<FormTable> list;
        try {
            String tenantId = ContextUtil.getCurrentUserTenantId();
            queryFilter = new QueryFilter(request, true);
            queryFilter.put("tenantId", tenantId);
            if (queryFilter.containsKey("isMain")) {
                queryFilter.put("isMain", Integer.parseInt(queryFilter.get("isMain").toString()));
            }
            if (queryFilter.containsKey("isPublished")) {
                queryFilter.put("isPublished", Integer.parseInt(queryFilter.get("isPublished").toString()));
            }
            list = formTableService.queryFormTableList(queryFilter);
            SysAuditThreadLocalHolder.putParamerter("success", true);
        } catch (NumberFormatException e) {
            e.printStackTrace();
            SysAuditThreadLocalHolder.putParamerter("success", false);
            return getResultDataError("query.failure");
        }
        return getResultDataSuccess("query.success", queryFilter.getPageBean().getTotalCount(), list);
    }

    /**
     * 据表的Id返回表和字段对象
     *
     * @param request 请求
     * @return ResultData
     */
    @ResponseBody
    @RequestMapping("/getByTableId")
    @Action(description = "据表的Id返回表和字段对象", exectype = "查询日志",
            detail = "据表的Id返回表和字段对象<#if success>成功<#else>失败</#if>")
    public ResultData getByTableId(HttpServletRequest request) {
        String tableId = RequestUtil.getString(request, "tableId");
        int mainTableIsPublished = RequestUtil.getInt(request, "mainTableIsPublished");
        int isExeTable = RequestUtil.getInt(request, "isExeTable");
        Map<String, Object> map = new HashMap<>(2);
        try {
            FormTable formTable = formTableService.getOneById(tableId);
            // 子表展示
            if (BeanUtils.isNotEmpty(formTable) && formTable.getIsMain() == FormTable.IS_NOT_MAIN) {
                String mainTableId = formTable.getMainTableId();
                if (StringUtil.isNotEmpty(mainTableId)) {
                    FormTable table = formTableService.getOneById(mainTableId);
                    // 为已发布的主表 添加一个子表时
                    if (mainTableIsPublished == FormTable.IS_PUBLISH) {
                        formTable.setMainTableDesc(table.getTableName());
                    } else {
                        formTable.setMainTableDesc(StringUtil.isEmpty(table
                                .getTableDesc()) ? table.getTableName() : table
                                .getTableDesc());
                    }
                    formTable.setMainTableName(table.getTableName());
                }
            }
            List<FormField> fieldList;
            if (isExeTable == FormTable.EXTERNAL) {
                // 如果是外部表查询列表，不包含删除的字段但是包含隐藏字段
                fieldList = formFieldService.getByTableIdContainHidden(tableId);
            } else {
                // 查询列表，不包含删除和隐藏字段的字段
                fieldList = formFieldService.getByTableIdNoHidden(tableId);
            }
            formTableService.convertFieldScript(fieldList);
            map.put("table", formTable);
            map.put("fields", fieldList);
            SysAuditThreadLocalHolder.putParamerter("success", true);
        } catch (Exception e) {
            e.printStackTrace();
            SysAuditThreadLocalHolder.putParamerter("success", false);
            return getResultDataError("operation.failure");
        }
        return getResultDataSuccess("operation.success", map);
    }


    /**
     * 删除自定义表。 如果表已经定义表单，那么表不可以删除。
     *
     * @param tableIds 表ids
     * @return JSON
     */
    @RequestMapping("/delByTableId")
    @ResponseBody
    @Action(description = "删除自定义表", exectype = "删除日志",
            detail = "删除自定义表<#if success>成功<#else>失败</#if>")
    public ResultData delByTableId(@RequestParam("tableIds") String tableIds) {
        String[] aryTableId = tableIds.split(",");
        try {
            Map<String, List<String>> map = formTableService.delByTableId(aryTableId);
            List<String> bindFormList = map.get("bindFormList");
            if (bindFormList.size() > 0) {
                //多个表被表单关联，提示被关联的表名列表
                return getResultDataError("formTable.delByTableId.bindForm", 0, bindFormList.toString());
            }
            List<String> bindTableList = map.get("bindTableList");
            if (bindTableList.size() > 0) {
                //多个表存在数据，提示存在数据的表名列表
                return getResultDataError("formTable.delByTableId.bindTable", 0, bindTableList.toString());
            }
            SysAuditThreadLocalHolder.putParamerter("success", true);
        } catch (Exception e) {
            e.printStackTrace();
            SysAuditThreadLocalHolder.putParamerter("success", false);
            return getResultDataError("delete.failure");
        }
        return getResultDataSuccess("delete.success");
    }

    /**
     * 重置自定义表。删除已生成的自定义物理表、删除标记为删除的字段
     * 1、已经绑定表单的自定义表不能重置
     *
     * @param tableId 表id
     * @return JSON
     */
    @RequestMapping("/reset")
    @ResponseBody
    @Action(description = "重置自定义表", exectype = "操作日志",
            detail = "重置自定义表<#if success>成功<#else>失败</#if>")
    public ResultData reset(@RequestParam("tableId") String tableId) {
        try {
            boolean isTableBindForm = formDefService.isTableBindForm(tableId);
            if (isTableBindForm) {
                return getResultDataError("formTable.reset.bindForm");
            }
            formTableService.reset(tableId);
            SysAuditThreadLocalHolder.putParamerter("success", true);
            return getResultDataSuccess("formTable.reset.success");
        } catch (Exception e) {
            e.printStackTrace();
            SysAuditThreadLocalHolder.putParamerter("success", false);
            return getResultDataError("formTable.reset.failure");
        }
    }

    /**
     * 取得自定义表明细
     *
     * @param tableId 表id
     * @return 自定义表明细
     */
    @RequestMapping("/getTableDetail")
    @ResponseBody
    @Action(description = "取得自定义表明细", exectype = "查询日志",
            detail = "取得自定义表明细<#if success>成功<#else>失败</#if>")
    public ResultData getTableDetail(@RequestParam("tableId") String tableId) {
        Map<String,Object> retMap = new HashMap(4);
        try {
            FormTable table = formTableService.getOneById(tableId);
            List<FormField> fields = formFieldService.getByTableId(tableId);
            String mainTableName = table.getTableName();
            if (table.getIsMain() == FormTable.IS_MAIN) {
                List<FormTable> subList = formTableService.querySubByMainTableId(tableId);
                retMap.put("subList", subList);
            } else {
                String mainTableId = table.getMainTableId();
                if (StringUtil.isNotEmpty(mainTableId)) {
                    FormTable tb = formTableService.getOneById(mainTableId);
                    if (tb.getIsMain() == FormTable.IS_MAIN) {
                        mainTableName = tb.getTableName();
                    }
                }
            }
            retMap.put("mainTableName", mainTableName);
            retMap.put("fields", fields);
            retMap.put("table", table);
            SysAuditThreadLocalHolder.putParamerter("success", true);
        } catch (Exception e) {
            e.printStackTrace();
            SysAuditThreadLocalHolder.putParamerter("success", false);
            return getResultDataError("query.failure");
        }
        return getResultDataSuccess("query.success", retMap);
    }

    /**
     * 是否包含子表
     *
     * @param request http请求
     * @return 封装对象
     */
    @RequestMapping("/hasSubTable")
    @ResponseBody
    @Action(description = "查询是否包含子表", exectype = "查询日志",
            detail = "查询是否包含子表<#if success>成功<#else>失败</#if>")
    public ResultData hasSubTable(HttpServletRequest request) {
        String formKey = RequestUtil.getString(request, "formKey");
        FormDef formDef = formDefService.getDefaultPublishedByFormKey(formKey);
        if (BeanUtils.isNotEmpty(formDef) && StringUtil.isNotEmpty(formDef.getTableId())) {
            List<FormTable> subTables = formTableService.getSubTableByMainTableId(formDef.getTableId());
            SysAuditThreadLocalHolder.putParamerter("success", true);
            if (BeanUtils.isNotEmpty(subTables)) {
                return getResultDataSuccess("formTable.subTable.exist");
            } else {
                return getResultDataError("formTable.subTable.not.exist");
            }
        }
        SysAuditThreadLocalHolder.putParamerter("success", false);
        return getResultDataError("formDef.not.find");
    }


    /**
     * 根据数据源及表名获取该数据库表
     *
     * @param request 请求
     */
    @RequestMapping("/getTableList")
    @ResponseBody
    @Action(description = "根据数据源及表名获取该数据库表", exectype = "查询日志",
            detail = "根据数据源及表名获取该数据库表<#if success>成功<#else>失败</#if>")
    public ResultData getTableList(HttpServletRequest request) {
        try {
            String alias = RequestUtil.getString(request, "dataSource");
            String table = RequestUtil.getString(request, "tableName");
            String dbType = dataSourceType.toLowerCase();
            BaseTableMeta meta = TableMetaFactory.getMetaData(alias, dbType);
            Map<String, String> map = meta.getTablesByName(table);
            SysAuditThreadLocalHolder.putParamerter("success", true);
            // 换回本地数据源
            DbContextHolder.clearDataSource();
            DbContextHolder.setDefaultDataSourceMy(dataSourceType);
            return getResultDataSuccess("query.success", map);
        } catch (Exception ex) {
            ex.printStackTrace();
            SysAuditThreadLocalHolder.putParamerter("success", false);
            // 换回本地数据源
            DbContextHolder.clearDataSource();
            DbContextHolder.setDefaultDataSourceMy(dataSourceType);
            return getResultDataError("formTable.getExtTable.error");
        }
    }

    /**
     * 根据数据源和表的名称获取外部表数据
     *
     * @param request 请求
     * @return ResultData
     */
    @RequestMapping("/getTableFields")
    @ResponseBody
    @Action(description = "根据数据源和表的名称获取外部表数据", exectype = "查询日志",
            detail = "根据数据源和表的名称获取外部表数据<#if success>成功<#else>失败</#if>")
    public ResultData getTableFields(HttpServletRequest request){
        //表名
        String tableName = RequestUtil.getString(request, "tableName");
        //数据源别名
        String alias = RequestUtil.getString(request, "dataSource");
        Map<String, Object> map;
        try {
            //默认数据源类型
            String dbType = dataSourceType.toLowerCase();
            BaseTableMeta meta = TableMetaFactory.getMetaData(alias, dbType);
            TableModel tableModel = meta.getTableByName(tableName);

            FormTable table = new FormTable();
            table.setTableName(tableName);
            table.setTableDesc(tableModel.getComment());
            // 取得字段列表
            List<FormField> fieldList = formTableService.convertFieldList(tableModel);
            formTableService.hideField(fieldList);
            // 换回本地数据源
            DbContextHolder.clearDataSource();
            DbContextHolder.setDefaultDataSourceMy(dataSourceType);
            map = new HashMap<>(3);
            map.put("table", table);
            map.put("fieldList", fieldList);
            map.put("pkList", tableModel.getPrimaryKey());
            SysAuditThreadLocalHolder.putParamerter("success", true);
        } catch (Exception e) {
            e.printStackTrace();
            SysAuditThreadLocalHolder.putParamerter("success", false);
            // 换回本地数据源
            DbContextHolder.clearDataSource();
            DbContextHolder.setDefaultDataSourceMy(dataSourceType);
            return getResultDataError("query.failure");
        }
        return getResultDataSuccess("query.success", map);
    }

    /**
     * 添加外部表-保存
     *
     * @param request 请求
     * @return ReturnData
     */
    @RequestMapping("/saveExtTable")
    @ResponseBody
    @Action(description = "添加或更新外部表", exectype = "添加或更新日志",
            detail = "添加或更新外部表<#if success>成功<#else>失败</#if>")
    public ResultData saveExtTable(HttpServletRequest request) {
        String tableJson = RequestUtil.getString(request, "table");
        String fieldsJson = RequestUtil.getString(request, "fields");
        tableJson = StringEscapeUtils.unescapeHtml4(tableJson);
        fieldsJson = StringEscapeUtils.unescapeHtml4(fieldsJson);
        FormTable table = (FormTable) JSONObject.toBean(JSONObject.fromObject(tableJson), FormTable.class);
        table.setTableName(table.getTableName().toLowerCase());
        List<FormField> list = formTableService.getByFormFieldJson(fieldsJson);
        //属性集合中是否有租户id
        boolean isNotExistTenantId = formTableService.isNotExistTenantId(list);
        if (isNotExistTenantId) {
            return getResultDataError("formTable.saveExtTable.warnTenantId");
        }
        table.setFieldList(list);
        String tableName = table.getTableName();
        String dsAlias = table.getDsAlias();
        if (formTableService.isTableNameExternalExisted(tableName, dsAlias)) {
            return getResultDataError("formTable.saveExtTable.warnTableName");
        }
        try {
            String tableId = UUIDUtils.getUUIDFor32();
            table.setTableId(tableId);
            formTableService.addExt(table);
            SysAuditThreadLocalHolder.putParamerter("success", true);
            return getResultDataSuccess("save.success");
        } catch (Exception ex) {
            ex.printStackTrace();
            SysAuditThreadLocalHolder.putParamerter("success", false);
            return getResultDataError("save.failure");
        }
    }

    /**
     * 添加自定义表
     *
     * @param request HttpServletRequest
     */
    @RequestMapping(UrlConstants.MODULE_FUNCTION_ADD_UPDATE)
    @ResponseBody
    @Action(description = "添加或更新自定义表", exectype = "添加或更新日志",
            detail = "添加或更新自定义表<#if success>成功<#else>失败</#if>")
    public ResultData saveTable(HttpServletRequest request) {
        String tableJson = RequestUtil.getString(request, "table");
        String fieldsJson = RequestUtil.getString(request, "fields");
        tableJson = StringEscapeUtils.unescapeHtml4(tableJson);
        fieldsJson = StringEscapeUtils.unescapeHtml4(fieldsJson);
        String categoryId = RequestUtil.getString(request, "categoryId");
        JSONObject tableJsonObj = JSONObject.fromObject(tableJson);
        FormTable table = (FormTable) JSONObject.toBean(tableJsonObj, FormTable.class);
        short isMain = table.getIsMain();
        String tId = "";
        try {
            List<FormField> fieldList = formTableService.getByFormFieldJson(fieldsJson);
            //属性集合中是否有租户id
            boolean isNotExistTenantId = formTableService.isNotExistTenantId(fieldList);
            //没有租户ID并且为主表的时候在filed中加入tenantId列
            if (isNotExistTenantId && isMain == FormTable.IS_MAIN) {
                FormField resource = formTableService.generateTenantField(tId);
                fieldList.add(resource);
            }
            //如果控制表单版本
            if (FormTable.NEED_VER.equals(table.getNeedVer())) {
                boolean isNotExistVersion = formTableService.isNotExistVersion(fieldList);
                if(isNotExistVersion){
                    FormField resource = formTableService.generateVersionField(tId);
                    fieldList.add(resource);
                }
            }
            //如果是主表 增加4个字段 创建人、创建时间、更新人、更新时间
            //20200513 主表增加密级字段dataPrivacyLevel
            if (isMain == FormConstants.DEFAULT_INT_ONE) {
                List<FormField> defaultFields = formTableService.addDefaultFields(tId);
                fieldList.addAll(defaultFields);
            //子表 增加排序字段
            }else{
                FormField sortField = formTableService.addDefaultSortField(tId);
                fieldList.add(sortField);
            }

            if (StringUtil.isEmpty(table.getTableId())) {
                if (formTableService.isTableNameExisted(table.getTableName())) {
                    return getResultDataError("formTable.saveExtTable.warnTableName");
                }
                String tableId = UUIDUtils.getUUIDFor32();
                table.setTableId(tableId);
                table.setFieldList(fieldList);
                table.setCategoryId(categoryId);
                formTableService.addFormTable(table);
                SysAuditThreadLocalHolder.putParamerter("success", true);
                return getResultDataSuccess("save.success");
            } else {
                FormTable origTable = formTableService.getOneById(table.getTableId());
                origTable.setTableName(table.getTableName());
                origTable.setTableDesc(table.getTableDesc());
                origTable.setCategoryId(categoryId);
                origTable.setFieldList(fieldList);
                origTable.setIsMain(table.getIsMain());
                origTable.setMainTableId(table.getMainTableId());
                origTable.setIsPublic(table.getIsPublic());
                origTable.setNeedVer(table.getNeedVer());
                formTableService.updateTable(origTable);
                SysAuditThreadLocalHolder.putParamerter("success", true);
                return getResultDataSuccess("update.success");
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            SysAuditThreadLocalHolder.putParamerter("success", false);
            return getResultDataError("save.failure");
        }
    }

    /**
     * 导出表定义xml。
     *
     * @param request  HttpServletRequest
     * @param response HttpServletResponse
     */
    @RequestMapping("/exportXml")
    @Action(description = "导出自定义表", exectype = "导出日志",
            detail = "导出自定义表<#if success>成功<#else>失败</#if>")
    public void exportXml(HttpServletRequest request, HttpServletResponse response) {
        String[] tableIds = RequestUtil.getStringAryByStr(request, "tableIds");
        Map<String, Boolean> map = new HashMap<>(4);
        map.put("bpmFormTable", true);
        map.put("bpmFormField", true);
        map.put("subTable", RequestUtil.getBoolean(request, "subTable"));
        map.put("identity", true);
        if (BeanUtils.isEmpty(tableIds)) {
            return;
        }
        try {
            String strXml = formTableService.exportXml(tableIds, map);
            String fileName = DateFormatUtil.getNowByString("yyyyMMddHHmmdd");
            if (tableIds.length == 1) {
                FormTable formtable = formTableService.getOneById(tableIds[0]);
                fileName = formtable.getTableDesc() + "_" + fileName;
            } else {
                fileName = FormConstants.STR_MULTIPLE_RECORDS + fileName;
            }

            response.setContentType("application/octet-stream");
            response.setCharacterEncoding("utf-8");
            response.setHeader("Content-Disposition", "attachment;filename="
                    + StringUtil.encodingString(fileName, "GBK", "ISO-8859-1")
                    + ".xml");
            response.getWriter().write(strXml);
            response.getWriter().flush();
            response.getWriter().close();
            SysAuditThreadLocalHolder.putParamerter("success", true);
        } catch (Exception e) {
            SysAuditThreadLocalHolder.putParamerter("success", false);
            e.printStackTrace();
        }
    }

    /**
     * 导入表的XML。
     *
     * @param request 请求
     * @return resultData
     */
    @RequestMapping("/importXml")
    @ResponseBody
    @Action(description = "导入自定义表", exectype = "导入日志",
            detail = "导入自定义表<#if success>成功<#else>失败</#if>")
    public ResultData importXml(MultipartHttpServletRequest request, @RequestParam("tenantId") String tenantId) {
        if(StringUtil.isNotEmpty(tenantId)){
            String[] splitStr=tenantId.split(",");
            if(splitStr.length>0){
                tenantId = splitStr[0];
            }
        }
        MultipartFile file = request.getFile("file");
        try {
            if(null != file){
                formTableService.importXmlCommonCheck(tenantId, file);
                formTableService.importXml(file.getInputStream(), tenantId);
                SysAuditThreadLocalHolder.putParamerter("success", true);
                return getResultDataSuccess("formTable.importXml.success");
            }
        } catch (Exception e) {
            e.printStackTrace();
            SysAuditThreadLocalHolder.putParamerter("success", false);
            return fail(e.getMessage());
        }
        return getResultDataError("operation.failure");
    }

    /**
     * 复制表
     *
     * @param request HttpServletRequest
     * @return ReturnData
     */
    @RequestMapping("/saveCopy")
    @ResponseBody
    @Action(description = "复制表", exectype = "添加日志",
            detail = "复制表<#if success>成功<#else>失败</#if>")
    public ResultData saveCopy(HttpServletRequest request) {
        String json = RequestUtil.getString(request, "json");
        //修改xss过滤引起的json参数问题
        json = StringEscapeUtils.unescapeHtml4(json);
        JSONArray jsonArray = JSONArray.fromObject(json);
        for (Object object : jsonArray) {
            JSONObject jsonObject = JSONObject.fromObject(object);
            String tableName = (String) jsonObject.get("tableName");
            if (formTableService.isTableNameExisted(tableName)) {
                return getResultDataError("formTable.saveExtTable.warnTableName");
            }
        }
        if (StringUtil.isEmpty(json)) {
            return getResultDataError("formTable.saveCopy.empty");
        }
        try {
            formTableService.saveCopy(json);
            SysAuditThreadLocalHolder.putParamerter("success", true);
            return getResultDataSuccess("save.success");
        } catch (Exception e) {
            e.printStackTrace();
            SysAuditThreadLocalHolder.putParamerter("success", false);
            return getResultDataError("save.failure");
        }
    }

    /**
     * 根据tableId取得表fields
     *
     * @param tableId 表ID
     * @return 表字段列表
     */
    @ResponseBody
    @RequestMapping("/getFieldsByTableId")
    @Action(description = "保存分组设置", exectype = "查询日志",
            detail = "保存分组设置<#if success>成功<#else>失败</#if>")
    public List<FormField> getFieldsByTableId(@RequestParam("tableId") String tableId) {
        List<FormField> fieldList = new ArrayList<>();
        try {
            fieldList = formFieldService.getByTableId(tableId);
            SysAuditThreadLocalHolder.putParamerter("success", true);
        } catch (Exception e) {
            SysAuditThreadLocalHolder.putParamerter("success", false);
            e.printStackTrace();
        }
        return fieldList;
    }

    /**
     * 分组设置保存
     *
     * @param request HttpServletRequest
     * @return ReturnData
     */
    @ResponseBody
    @RequestMapping("/teamSave")
    @Action(description = "保存分组设置", exectype = "添加日志",
            detail = "保存分组设置<#if success>成功<#else>失败</#if>")
    public ResultData teamSave(HttpServletRequest request) {
        String json = RequestUtil.getString(request, "json");
        json = StringEscapeUtils.unescapeHtml4(json);
        String tableId = RequestUtil.getString(request, "tableId");
        FormTable bpmFormTable = formTableService.getOneById(tableId);
        try {
            bpmFormTable.setTeam(json);
            formTableService.update(bpmFormTable);
            SysAuditThreadLocalHolder.putParamerter("success", true);
            return getResultDataSuccess("save.success");
        } catch (Exception e) {
            e.printStackTrace();
            SysAuditThreadLocalHolder.putParamerter("success", false);
            return getResultDataError("save.failure");
        }
    }

    /**
     * 验证加密，解密类和方法
     * 输入格式为 serviceId +"." + 方法名。
     *
     * @param handler 要验证的类.方法
     * @return 返回结果JSON
     */
    @RequestMapping("/validHandler")
    @ResponseBody
    @Action(description = "验证加密，解密类和方法", exectype = "查询日志",
            detail = "验证加密，解密类和方法<#if success>成功<#else>失败</#if>")
    public ResultData validHandler(@RequestParam("handler") String handler) {
        int rtn = AppUtil.isHandlerValidNoCmd(handler, new Class[]{String.class});
        String msg = "";
        try {
            if (rtn == FormConstants.DEFAULT_INT_ZERO) {
                return getResultDataSuccess("formTable.validHandler.success");
            }
            switch (rtn) {
                case -1:
                    msg = "formTable.validHandler.invalidFormat";
                    break;
                case -2:
                    msg = "formTable.validHandler.noService";
                    break;
                case -3:
                    msg = "formTable.validHandler.noMethod";
                    break;
                default:
                    msg = "formTable.validHandler.other";
                    break;
            }
            SysAuditThreadLocalHolder.putParamerter("success", true);
        } catch (Exception e) {
            e.printStackTrace();
            SysAuditThreadLocalHolder.putParamerter("success", false);
        }
        return getResultDataError(msg);
    }


    /**
     * 通过字段描述生成对应的字段名称
     *
     * @param request 请求
     * @return Object 字段名称
     */
    @RequestMapping("/getFieldKey")
    @ResponseBody
    @Action(description = "通过字段描述生成对应的字段名称", exectype = "查询日志",
            detail = "通过字段描述生成对应的字段名称<#if success>成功<#else>失败</#if>")
    public ResultData getFieldKey(HttpServletRequest request) {
        String fieldDesc = RequestUtil.getString(request, "fieldDesc");
        String fieldName;
        try {
            fieldName = PinyinUtil.getPinYinHeadCharFilter(fieldDesc);
            SysAuditThreadLocalHolder.putParamerter("success", true);
        } catch (Exception e) {
            e.printStackTrace();
            SysAuditThreadLocalHolder.putParamerter("success", false);
            return getResultDataError("operation.failure");
        }
        return getResultDataSuccess("operation.success", fieldName);
    }

    /**
     * 判断表中是否有数据
     *
     * @param tableId 表ID
     * @return 表中记录条数
     */
    @RequestMapping("/isExistDataInTable")
    @ResponseBody
    @Action(description = "查询表中是否有数据", exectype = "查询日志",
            detail = "查询表中是否有数据<#if success>成功<#else>失败</#if>")
    public ResultData isExistDataInTable(@RequestParam("tableId") String tableId) {
        int count = FormConstants.DEFAULT_INT_ZERO;
        try {
            FormTable formTable = formTableService.getOneById(tableId);
            if (BeanUtils.isNotEmpty(formTable) && formTable.getIsPublished().equals(FormTable.IS_PUBLISH)) {
                String tableName = TableModel.getCustomTableName(formTable.getTableName());
                count = formTableService.countDataInTable(tableName);
            }
            SysAuditThreadLocalHolder.putParamerter("success", true);
        } catch (Exception e) {
            e.printStackTrace();
            SysAuditThreadLocalHolder.putParamerter("success", false);
            return getResultDataError("operation.failure");
        }
        return getResultDataSuccess("operation.success", count);
    }

    /**
     * 获取表字段及子表数据
     *
     * @param request request
     * @return 转为json字符串的数据
     */
    @ResponseBody
    @RequestMapping("/getJsonByFormKey")
    @Action(description = "获取表字段及子表数据", exectype = "查询日志",
            detail = "获取表字段及子表数据<#if success>成功<#else>失败</#if>")
    public String getJsonByTableId(HttpServletRequest request) {
        String formKey = RequestUtil.getString(request, "formKey");
        JSONObject jsonTable = new JSONObject();
        try {
            jsonTable = formTableService.getjson(formKey);
            SysAuditThreadLocalHolder.putParamerter("success", true);
        } catch (Exception e) {
            e.printStackTrace();
            SysAuditThreadLocalHolder.putParamerter("success", false);
        }
        return jsonTable.toString();
    }

    /**
     * 根据tableId获取表及子表及关联属性
     *
     * @return FormTable
     */
    @RequestMapping("/getTableById")
    @ResponseBody
    @Action(description = "获取表及子表及关联属性", exectype = "查询日志",
            detail = "获取表及子表及关联属性<#if success>成功<#else>失败</#if>")
    public FormTable getTableById(HttpServletRequest request, @RequestParam("tableId") String tableId) {
        Boolean incHide = RequestUtil.getBoolean(request, "incHide", false);
        int need = 0;
        if (incHide) {
            need = 1;
        }
        FormTable mainTable = null;
        // need
        // 0为正常字段
        // 1为正常字段加上隐藏字段
        // 2为正常字段加上逻辑删除字段
        try {
            mainTable = formTableService.getByTableId(tableId, need);
            SysAuditThreadLocalHolder.putParamerter("success", true);
        } catch (Exception e) {
            SysAuditThreadLocalHolder.putParamerter("success", false);
        }
        return mainTable;
    }

    /**
     * 表单编辑的查询设置中
     * 根据tableId获取表及子表的id和name
     * 获取所有列表类型自定义对话框
     * 获取所有组合对话框
     * 获取表字段
     *
     * @return map
     */
    @RequestMapping("/getByMainTableId")
    @ResponseBody
    @Action(description = "获取所有列表类型自定义对话框等数据", exectype = "查询日志",
            detail = "获取所有列表类型自定义对话框等数据<#if success>成功<#else>失败</#if>")
    public ResultData getByMainTableId(@RequestParam("tableId") String tableId) {
        try {
            Map<String, Object> resultMap = new HashMap<>(16);
            //获取表的id和name
            List<Map<String, String>> list = formTableService.getByMainTableId(tableId);
            resultMap.put("tableMeans", list);
            //获取列表对话框数据
            List<FormDialog> dialogList = formDialogService.getAllDialogs();
            resultMap.put("allDialogs", dialogList);
            //获取组合对话框列表
            List<FormCombinationDialog> combinationList = formCombinationDialogService.getAllCombinationDialogs();
            resultMap.put("allCombinations", combinationList);
            // 0为正常字段
            int need = 0;
            FormTable mainTable = formTableService.getByTableId(tableId, need);
            resultMap.put("mainTable", mainTable);
            SysAuditThreadLocalHolder.putParamerter("success", true);
            return getResultDataSuccess("query.success", resultMap);
        } catch (Exception e) {
            e.printStackTrace();
            SysAuditThreadLocalHolder.putParamerter("success", false);
            return getResultDataError("query.failure");
        }
    }

    /**
     * 获取流程子表树
     * @param request http请求
     * @return 结果集
     */
    @RequestMapping("/getSubTree")
    @ResponseBody
    @Action(description = "获取流程子表树", detail = "获取流程子表树")
    public ResultData getSubTree(HttpServletRequest request) {
        String ctx = request.getContextPath();
        String tableId = RequestUtil.getString(request, "tableId");
        String nodeId = RequestUtil.getString(request, "nodeId");
        String procDefId = RequestUtil.getString(request, "procDefId");
        String parentProcDefId = RequestUtil.getString(request, "parentProcDefId");

        StringBuilder sb = new StringBuilder("[");
        if (StringUtil.isEmpty(tableId)) {
            sb.append("]");
            return getResultDataError("formTable.not.found", 1, sb.toString());
        }

        List<FormTable> subTableList = formTableService.getSubTableByMainTableId(tableId);

        sb.append("{id:").append("-1").append(",isTable:").append("1")
                .append("").append(",name:\"").append("中间业务表").append("\"")
                .append(",icon:\"").append("").append("\"")
                .append(",showName: \"").append("中间业务表")
                .append("\",children:[");

        sb.append("{id:").append("\"b.BUS_FLOW_RUNID\"").append(",isTable:")
                .append("0").append("").append(",fieldType:\"")
                .append("number").append("\"").append(",name:\"")
                .append("b.BUS_FLOW_RUNID").append("\"").append(",icon:\"")
                .append("").append("\"").append(",showName: \"")
                .append("流程运行ID").append("\"},");

        sb.append("{id:").append("\"b.BUS_CREATOR_ID\"").append(",isTable:")
                .append("0").append("").append(",fieldType:\"")
                .append("number").append("\"").append(",name:\"")
                .append("b.BUS_CREATOR_ID").append("\"").append(",icon:\"")
                .append("").append("\"").append(",showName: \"")
                .append("创建人ID").append("\"},");

        sb.append("{id:").append("\"b.BUS_ORG_ID\"").append(",isTable:")
                .append("0").append("").append(",fieldType:\"")
                .append("number").append("\"").append(",name:\"")
                .append("b.BUS_ORG_ID").append("\"").append(",icon:\"")
                .append("").append("\"").append(",showName: \"").append("组织ID")
                .append("\"}");

        sb.append("]},");

        for (FormTable subTable : subTableList) {
            String subTableId = subTable.getTableId();
            List<FormField> fieldList = formFieldService.getByTableId(subTableId);
            String sign = "<img src='" + ctx + "/workflowStatic/style/res/no.png'>";

            SubTableRights subTableRights;
            if (StringUtil.isEmpty(parentProcDefId)) {
                subTableRights = subTableRightsService.getByProcDefIdAndNodeId(procDefId, nodeId, subTableId);
            }else{
                subTableRights = subTableRightsService.getByProcDefIdAndNodeIdAndParent(procDefId, nodeId, subTableId, parentProcDefId);
            }

            if (subTableRights != null) {
                sign = "<img src='" + ctx + "/workflowStatic/style/res/yes.png'>";
            }

            sb.append("{id:\"").append(subTable.getTableId()).append("\"")
                    .append(",isTable:").append("1").append("")
                    .append(",name:\"").append(subTable.getTableName())
                    .append("\"").append(",icon:\"").append("").append("\"")
                    .append(",img:\"").append(sign).append("\"")
                    .append(",showName: \"")
                    .append(subTable.getTableName())
                    .append("(" + subTable.getTableDesc() + ")")
                    .append(sign).append("\",children:[");

            for (FormField formField : fieldList) {
                sb.append("{id:\"").append(formField.getFieldId()).append("\"")
                        .append(",isTable:").append("0").append("")
                        .append(",fieldType:\"")
                        .append(formField.getFieldType()).append("\"")
                        .append(",name:\"a.f_")
                        .append(formField.getFieldName()).append("\"")
                        .append(",icon:\"").append("").append("\"")
                        .append(",showName: \"")
                        .append(formField.getFieldName())
                        .append("(" + formField.getFieldDesc() + ")")
                        .append("\"},");
            }

            if (!subTableList.isEmpty()) {
                sb.deleteCharAt(sb.length() - 1);
            }

            sb.append("]},");
        }

        if (!subTableList.isEmpty()) {
            sb.deleteCharAt(sb.length() - 1);
        }
        sb.append("]");

        return getResultDataSuccess("operation.success", sb.toString());
    }

}